Assignment Objectives
Master the fundamental concepts of point estimation and
performance metrics
Understand the theoretical foundation of the method of moments
estimator (MME)
Implement MME in R, incorporating numerical approximation
methods
Use of AI Tools
Policy on AI Tool Use: Students must adhere to the
AI tool policy specified in the course syllabus. The direct copying of
AI-generated content is strictly prohibited. All submitted work must
reflect your own understanding; where external tools are consulted,
content must be thoroughly rephrased and synthesized in your own
words.
Code Inclusion Requirement: Any code included in
your essay must be properly commented to explain the purpose and/or
expected output of key code lines. Submitting AI-generated code without
meaningful, student-added comments will not be accepted.
Log-logistic Distribution
The log-logistic distribution (also known as the Fisk distribution)
is a continuous probability distribution that is particularly useful in
contexts where data exhibit non-negative, skewed behavior and where the
hazard rate is unimodal (increases to a peak and then decreases). It has
been widely used in the areas such as survival analysis and reliability
engineering, environmental science, economics, pharmacology, finance and
risk management, etc.
For given shape parameter \(\beta\)
and scale parameter \(\alpha\), the
cumulative distribution function
\[
F(x) = \frac{1}{1+(x/\alpha)^{-\beta}}
\]
As an exercise, you can derive the density in the following form
\[
f(x) =
\frac{(\beta/\alpha)(x/\alpha)^{\beta-1}}{[1+(x/\alpha)^\beta]^2}, \ \
\text{ for } \ \ x > 0.
\]
After some algebra, we can find the \(k\)th moment
\[
\mu_k = E[X^k] = \alpha^k B\left(1+\frac{k}{\beta}, 1 - \frac{k}{\beta}
\right).
\]
This assignment will focus on finding MME of parameters \(\alpha\) and \(\beta\) based on a real-world application
data set.
Question 2: Distribution of Recovery Time from A
Surgery
Time to recovery (in days) after a specific knee surgery procedure.
This follows a typical log-logistic pattern in medical
survival/recovery analysis:
8.23, 12.74, 14.83, 16.61, 18.16, 19.55, 20.80, 21.94, 23.00, 23.98, 24.89, 25.75, 26.56,
27.34, 28.08, 28.79, 29.48, 30.15, 30.81, 31.45, 32.08, 32.70, 33.31, 33.92, 34.53, 35.13,
35.73, 36.33, 36.93, 37.53, 38.14, 38.75, 39.37, 40.00, 40.64, 41.29, 41.95, 42.63, 43.33,
44.05, 44.79, 45.56, 46.36, 47.20, 48.08, 49.02, 50.03, 51.12, 52.32, 53.65
Based on the above data to perform the following analysis.
- Using method of moment estimation to estimate \(\alpha\) and \(\beta\), denoted by \(\hat{\alpha}\) and \(\hat{\beta}\), respectively.
# --------------- STORING SAMPLE DATA AND CALCULATING M1 AND M2 ------------------------------------------------
recovery_sample <- c(8.23, 12.74, 14.83, 16.61, 18.16, 19.55, 20.80, 21.94, 23.00, 23.98, 24.89, 25.75, 26.56,
27.34, 28.08, 28.79, 29.48, 30.15, 30.81, 31.45, 32.08, 32.70, 33.31, 33.92, 34.53, 35.13,
35.73, 36.33, 36.93, 37.53, 38.14, 38.75, 39.37, 40.00, 40.64, 41.29, 41.95, 42.63, 43.33,
44.05, 44.79, 45.56, 46.36, 47.20, 48.08, 49.02, 50.03, 51.12, 52.32, 53.65)
# recovery_sample: store sample recovery times as a vector
m1 <- mean(recovery_sample)
# m1: first moment of the sample
m2 <- mean(recovery_sample^2)
# m2: second moment of the sample
# --------------- CREATING BETA ESTIMATOR FUNCTION ------------------------------------------------------------
beta_estimator <- function(K, m1, m2)
# beta_estimator: function with three arguments
# B: Beta. We will solve for this later using numerical approximation.
# m1: first moment of the sample
# m2: second moment of the sample
{
# this bracket begins the definition of the function
num <- beta(1 + 2/K, 1 - 2/K)
# num: is the numerator of our equation isolating Beta
denom <- (beta(1 + 1/K, 1 - 1/K))^2
# denom: is the denominator of our equation isolating Beta
result <- num / denom - m2 / m1^2
# result: the simplified system of equations of population and sample moments where Beta is isolated
# We will set this equal to zero and solve for Beta later.
return(result)
}
# this bracket ends the definition of the function
# --------------- GRAPHING TO ESTIMATE LOCATION OF X INT -----------------------------------------------------
x_vals <- seq(5, 10, length.out = 50)
# x_vals: numeric vector of 50 equally spaced values starting at 5 and ending at 10
dframe <- data.frame(x = x_vals, y = beta_estimator(x_vals, m1, m2))
#dframe: data frame with two columns
# x: the vector of input values (x_vals)
# y: the vector of estimated Beta values
beta_estimator.plot <- ggplot(dframe, aes(x = x, y = y)) +
# plot dframe data. use x as x-axis and y as y-axis
geom_line(color = "steelblue", size = 1) +
# draw a blue line connecting all the data points
geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5) +
# create dashed line along the x-axis
geom_vline(xintercept = 0, linetype = "dashed", alpha = 0.5) +
# create dashed line along the y-axis
labs(title = "The curve of function beta_estimator",
x = "Beta_Estimator",
y = "Height of Function") +
# Create titles
theme(plot.title = element_text(hjust = 0.5),
# Centers the plot title
plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
# Adds extra padding around the graph so titles are less cramped
ggplotly(beta_estimator.plot) # Reads the plot we created and creates an interactive widget
Insight: The X-intercept is somewhere between 5 and
7. In the next step, we will look for a solution (beta hat) along that
interval.
# --------------- USING NUMERICAL APPROXIMATION TO FIND BETA HAT ------------------------------------------------
beta_hat <- uniroot(beta_estimator, interval = c(5, 7), m1, m2)$root
alpha_hat <- m1 / beta(1 + 1/beta_hat, 1 - 1/beta_hat)
# We plug beta hat back into the equation for the first moment to find alpha hat
pander(cbind(beta_hat = beta_hat, alpha_hat = alpha_hat))# cbind: creates a two column matrix for beta_hat and alpha_hat. Titles are alpha_hat and beta_hat. pander renders a clean readable table
- Since the moment estimates \(\hat{\alpha}\) and \(\hat{\beta}\) are random, construct
bootstrap sampling distributions for each. To visualize these
distributions, plot separate bootstrap histograms for \(\hat{\alpha}\) and \(\hat{\beta}\). then, overlay a smooth
density curve on each histogram using Gaussian kernel density
estimation. Finally, describe the patterns of these density curves.
# -----------------DEFINING THE BOOTSTRAP FUNCTION -----------------------------------------------------------------------
bootstrap_moments <- function(data, B)
# bootstrap_moments: function with two arguments
# data: the random sample from the population with which you will make bootstrap samples
# B: the number of bootstrap samples you plan to create
{
# this bracket begins the definition of the function
n <- length(data)
# n: the number of observations in your random sample
t_obs_first_mom <- mean(data)
t_obs_second_mom <- mean(data^2)
# t_obs: the computed statistic for your original random sample. This only needs to be computed once.
# t_obs_first_mom represents your first sample moment and t_obs_second_mom is your second sample moment.
# this will not become part of your bootstrap distribution. This is your actual estimate from the real world.
boot_first_mom_dist <- numeric(B)
boot_second_mom_dist <- numeric(B)
# boot_dist: empty vector of length B that will eventually store all the bootstrap statistics you will compute
for (b in 1:B)
{
# everything inside of this bracket will loop B times, filling the vectors boot_first_mom_dist and boot_second_mom_dist
indices <- sample(1:n, n, replace = TRUE)
# the sample function samples with replacement from the vector 1:n (the integers 1,2,3, ... n) until sample size is n
# the result is a vector called indices which stores the position of data values we'd like in our bootstrap sample
bootstrap_sample <- data[indices]
# we index our data with the indices vector to create our bootstrap sample
boot_first_mom_dist[b] <- mean(bootstrap_sample)
# we compute the first moment of our bootstrap sample
boot_second_mom_dist[b] <- mean(bootstrap_sample^2)
# we compute the second moment of our bootstrap sample
# and then feed those values into our bootstrap distribution vectors, filling in position b
}
# everything after this bracket is outside the loop
return(list(observed_first_mom = t_obs_first_mom, observed_second_mom = t_obs_second_mom, distribution_first_mom = boot_first_mom_dist,
distribution_second_mom = boot_second_mom_dist))
# save all of our data in a list
}
# this bracket ends the definition of the function
# ----------------- CREATING OUR BOOTSTRAP ESTIMATES -----------------------------------------------------------------------
boot_moms <- bootstrap_moments(recovery_sample,5000)
# boot_moms: a list of 5000 bootstrap first moments, 5000 bootstrap second moments, as well as the first and second moments from the sample data.
beta_bootstrap_estimates <- numeric(length(boot_moms$distribution_first_mom))
alpha_bootstrap_estimates <- numeric(length(boot_moms$distribution_first_mom))
# Creating empty vectors the length of distribution_first_mom
# We will use these to store our alpha and beta estimates
for (i in 1:length(beta_bootstrap_estimates))
# everything inside of this bracket will loop 5000 times, filling the vectors beta_bootstrap_estimates and alpha_bootstrap_estimates
{
m1b <- boot_moms$distribution_first_mom[i]
# we gather the i-th first bootstrap moment
m2b <- boot_moms$distribution_second_mom[i]
# we gather the i-th second bootstrap moment
beta_bootstrap_estimates[i] <- uniroot(beta_estimator, interval = c(2, 15), m1 = m1b, m2 = m2b)$root
# we compute the the i-th beta estimate
alpha_bootstrap_estimates[i] <- m1b / beta(1 + 1/beta_bootstrap_estimates[i], 1 - 1/beta_bootstrap_estimates[i])
# we compute the the i-th alpha estimate
# and then feed those values into our bootstrap estimate vectors, filling in position i
}
Answer: The bootstrap sampling distribution of alpha
hat is approximately normal. It appears bell‑shaped, unimodal, and
symmetric around its center. In contrast, the bootstrap distribution of
beta hat is noticeably right‑skewed. This difference arises from the way
each estimator is constructed. The estimator alpha hat is a smooth,
nearly linear transformation of the sample mean. Meanwhile, beta hat is
obtained as the numerical root of a nonlinear moment equation involving
the ratio 𝑚2 / 𝑚1^ 2 . Because the second moment 𝑚2 has higher sampling
variability and is more sensitive to large observations, the sampling
distribution of beta hat develops a longer right tail.
# ----------------- GRAPHING OUR BOOTSTRAP ESTIMATE DISTRIBUTIONS -----------------------------------------------------------------------
df_alpha <- data.frame(alpha_hat = alpha_bootstrap_estimates)
# df_alpha: ggplot cannot take vectors, so we need to create a data frame to give it
df_beta <- data.frame(beta_hat = beta_bootstrap_estimates)
p_alpha <- ggplot(df_alpha, aes(x = alpha_hat)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "skyblue", color = "white", alpha = 0.7) +
geom_density(kernel = "gaussian", color = "blue", linewidth = 1.2) +
labs(
title = "Bootstrap Distribution of α̂",
x = expression(hat(alpha)),
y = "Density"
) +
theme_minimal()
p_alpha

p_beta <- ggplot(df_beta, aes(x = beta_hat)) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "salmon", color = "white", alpha = 0.7) +
geom_density(kernel = "gaussian", color = "red", linewidth = 1.2) +
labs(
title = "Bootstrap Distribution of β̂",
x = expression(hat(beta)),
y = "Density"
) +
theme_minimal()
p_beta

LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgNDogTWV0aG9kcyBvZiBNb21lbnQgRXN0aW1hdGlvbiINCmF1dGhvcjogIk1hdHRoZXcgR3JheSINCmRhdGU6ICJEdWU6IEZlYnVyYXJ5IDI0LCAyMDI2Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIHRoZW1lOiBsdW1lbg0KICBwZGZfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiAzDQogICAgZmlnX2hlaWdodDogMw0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCiNUT0M6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICJUYWJsZSBvZiBDb250ZW50cyI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuMmVtOw0KICBkaXNwbGF5OiBibG9jazsNCiAgY29sb3I6IG5hdnk7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCg0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLw0KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLw0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTVweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KDQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogIGxpYnJhcnkocGxvdGx5KQ0KfQ0KIyMjIw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUNCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91IGNhbiBjaG9vc2UgdG8gaW5jbHVkZSB0aGUgd2FybmluZyBtZXNzYWdlcyBpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgZmlsZS4gDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGluIHRoZSBvdXRwdXQgZmlsZS4NCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BDQogICAgICAgICAgICAgICAgICAgICAgKSAgDQpgYGANCiANCiBcDQogDQojIyAqKkFzc2lnbm1lbnQgT2JqZWN0aXZlcyoqIA0KDQoqIE1hc3RlciB0aGUgZnVuZGFtZW50YWwgY29uY2VwdHMgb2YgcG9pbnQgZXN0aW1hdGlvbiBhbmQgcGVyZm9ybWFuY2UgbWV0cmljcw0KDQoqIFVuZGVyc3RhbmQgdGhlIHRoZW9yZXRpY2FsIGZvdW5kYXRpb24gb2YgdGhlIG1ldGhvZCBvZiBtb21lbnRzIGVzdGltYXRvciAoTU1FKQ0KDQoqIEltcGxlbWVudCBNTUUgaW4gUiwgaW5jb3Jwb3JhdGluZyBudW1lcmljYWwgYXBwcm94aW1hdGlvbiBtZXRob2RzDQoNClwNCg0KKipVc2Ugb2YgQUkgVG9vbHMqKg0KDQoqKlBvbGljeSBvbiBBSSBUb29sIFVzZSoqOiBTdHVkZW50cyBtdXN0IGFkaGVyZSB0byB0aGUgQUkgdG9vbCBwb2xpY3kgc3BlY2lmaWVkIGluIHRoZSBjb3Vyc2Ugc3lsbGFidXMuIFRoZSBkaXJlY3QgY29weWluZyBvZiBBSS1nZW5lcmF0ZWQgY29udGVudCBpcyBzdHJpY3RseSBwcm9oaWJpdGVkLiBBbGwgc3VibWl0dGVkIHdvcmsgbXVzdCByZWZsZWN0IHlvdXIgb3duIHVuZGVyc3RhbmRpbmc7IHdoZXJlIGV4dGVybmFsIHRvb2xzIGFyZSBjb25zdWx0ZWQsIGNvbnRlbnQgbXVzdCBiZSB0aG9yb3VnaGx5IHJlcGhyYXNlZCBhbmQgc3ludGhlc2l6ZWQgaW4geW91ciBvd24gd29yZHMuDQoNCioqQ29kZSBJbmNsdXNpb24gUmVxdWlyZW1lbnQqKjogQW55IGNvZGUgaW5jbHVkZWQgaW4geW91ciBlc3NheSBtdXN0IGJlIHByb3Blcmx5IGNvbW1lbnRlZCB0byBleHBsYWluIHRoZSBwdXJwb3NlIGFuZC9vciBleHBlY3RlZCBvdXRwdXQgb2Yga2V5IGNvZGUgbGluZXMuIFN1Ym1pdHRpbmcgQUktZ2VuZXJhdGVkIGNvZGUgd2l0aG91dCBtZWFuaW5nZnVsLCBzdHVkZW50LWFkZGVkIGNvbW1lbnRzIHdpbGwgbm90IGJlIGFjY2VwdGVkLg0KDQpcDQoNCioqTG9nLWxvZ2lzdGljIERpc3RyaWJ1dGlvbioqDQoNClRoZSBsb2ctbG9naXN0aWMgZGlzdHJpYnV0aW9uIChhbHNvIGtub3duIGFzIHRoZSBGaXNrIGRpc3RyaWJ1dGlvbikgaXMgYSBjb250aW51b3VzIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbiB0aGF0IGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgaW4gY29udGV4dHMgd2hlcmUgZGF0YSBleGhpYml0IG5vbi1uZWdhdGl2ZSwgc2tld2VkIGJlaGF2aW9yIGFuZCB3aGVyZSB0aGUgaGF6YXJkIHJhdGUgaXMgdW5pbW9kYWwgKGluY3JlYXNlcyB0byBhIHBlYWsgYW5kIHRoZW4gZGVjcmVhc2VzKS4gSXQgaGFzIGJlZW4gd2lkZWx5IHVzZWQgaW4gdGhlIGFyZWFzIHN1Y2ggYXMgc3Vydml2YWwgYW5hbHlzaXMgYW5kIHJlbGlhYmlsaXR5IGVuZ2luZWVyaW5nLCBlbnZpcm9ubWVudGFsIHNjaWVuY2UsIGVjb25vbWljcywgcGhhcm1hY29sb2d5LCBmaW5hbmNlIGFuZCByaXNrIG1hbmFnZW1lbnQsIGV0Yy4gDQoNCkZvciBnaXZlbiBzaGFwZSBwYXJhbWV0ZXIgJFxiZXRhJCBhbmQgc2NhbGUgcGFyYW1ldGVyICRcYWxwaGEkLCB0aGUgY3VtdWxhdGl2ZSBkaXN0cmlidXRpb24gZnVuY3Rpb24NCg0KJCQNCkYoeCkgPSBcZnJhY3sxfXsxKyh4L1xhbHBoYSleey1cYmV0YX19DQokJA0KDQpBcyBhbiBleGVyY2lzZSwgeW91IGNhbiBkZXJpdmUgdGhlIGRlbnNpdHkgaW4gdGhlIGZvbGxvd2luZyBmb3JtDQoNCiQkDQpmKHgpID0gXGZyYWN7KFxiZXRhL1xhbHBoYSkoeC9cYWxwaGEpXntcYmV0YS0xfX17WzErKHgvXGFscGhhKV5cYmV0YV1eMn0sIFwgXCBcdGV4dHsgZm9yIH0gXCBcIHggPiAwLg0KJCQNCg0KQWZ0ZXIgc29tZSBhbGdlYnJhLCB3ZSBjYW4gZmluZCB0aGUgJGskdGggbW9tZW50DQoNCiQkDQpcbXVfayA9IEVbWF5rXSA9IFxhbHBoYV5rIEJcbGVmdCgxK1xmcmFje2t9e1xiZXRhfSwgMSAtIFxmcmFje2t9e1xiZXRhfSBccmlnaHQpLg0KJCQNCg0KVGhpcyBhc3NpZ25tZW50IHdpbGwgZm9jdXMgb24gZmluZGluZyBNTUUgb2YgcGFyYW1ldGVycyAkXGFscGhhJCBhbmQgJFxiZXRhJCBiYXNlZCBvbiBhIHJlYWwtd29ybGQgYXBwbGljYXRpb24gZGF0YSBzZXQuDQoNCg0KXA0KDQojIyAqKlF1ZXN0aW9uIDE6IERlcml2ZSB0aGUgbG9nLWxvZ2lzdGljIGRlbnNpdHkgZnVuY3Rpb24gKioNCg0KR2l2ZW4gdGhlIENERiBvZiB0aGUgdHdvLXBhcmFtZXRlciBsb2ctbG9naXN0aWMgZGlzdHJpYnV0aW9uDQoNCiQkDQpGKHgpID0gXGZyYWN7MX17MSsoeC9cYWxwaGEpXnstXGJldGF9fS4NCiQkDQoNClwNCg0KYGBge3J9DQojIC0tLS0tLS0tLS0tLS0gQ09NUFVURSBUSEUgREVSSVZBVElWRSBVU0lORyBSIC0tLS0tLS0tLS0tLS0tLS0NCkNERl9GaXNrIDwtIGV4cHJlc3Npb24oMSAvICgxICsgKHgvYWxwaGEpXigtYmV0YSkpKQ0KIyBTdG9yZSB0aGUgQ0RGIGFzIGFuIGV4cHJlc3Npb24NClBERl9GaXNrIDwtIEQoQ0RGX0Zpc2ssICJ4IikNCiMgQ29tcHV0ZSB0aGUgZGVyaXZhdGl2ZSBvZiB0aGUgZXhwcmVzc2lvbiB3aXRoIHJlc3BlY3QgdG8geA0KYGBgDQpSZXdyaXRlIHRoZSBDREYgYXMNClxbDQpGKHgpID0gXGxlZnQoIDEgKyAoeC9cYWxwaGEpXnstXGJldGF9IFxyaWdodCleey0xfQ0KXF0NCg0KXA0KDQpBcHBseSB0aGUgY2hhaW4gcnVsZToNClxbDQpmKHgpDQo9IC0gXGxlZnQoIDEgKyAoeC9cYWxwaGEpXnstXGJldGF9IFxyaWdodCleey0yfQ0KICBcY2RvdCAtXGJldGEgKHgvXGFscGhhKV57LVxiZXRhIC0gMX0gXGNkb3QgXGZyYWN7MX17XGFscGhhfQ0KXF0NCg0KXA0KDQpTaW1wbGlmeToNClxbDQpmKHgpDQo9IFxsZWZ0KCAxICsgKHgvXGFscGhhKV57LVxiZXRhfSBccmlnaHQpXnstMn0NCiAgXGNkb3QgXGJldGEvXGFscGhhICh4L1xhbHBoYSleey1cYmV0YSAtIDF9DQpcXQ0KDQpcDQoNClJlLXdyaXRlIHRoZSBmaXJzdCB0ZXJtOg0KXFsNCmYoeCkNCj0gXGxlZnQoIFxmcmFjeyh4L1xhbHBoYSleXGJldGEgKyAxfXsoeC9cYWxwaGEpXlxiZXRhfSBccmlnaHQpXnstMn0NCiAgXGNkb3QgXGZyYWN7XGJldGF9e1xhbHBoYX0gKHgvXGFscGhhKV57LVxiZXRhIC0gMX0NClxdDQoNClwNCg0KQnJlYWsgYXBhcnQgdGhlIGZpcnN0IHRlcm06IA0KXFsNCmYoeCkNCj0gXGxlZnQoICh4L1xhbHBoYSleXGJldGEgKyAxIFxyaWdodCleey0yfQ0KICBcY2RvdCAoeC9cYWxwaGEpXnsyXGJldGF9DQogIFxjZG90IFxmcmFje1xiZXRhfXtcYWxwaGF9ICh4L1xhbHBoYSleey1cYmV0YSAtIDF9DQpcXQ0KDQpcDQoNCkNvbWJpbmUgdGVybXM6IA0KXFsNCmYoeCkNCj0gXGxlZnQoICh4L1xhbHBoYSleXGJldGEgKyAxIFxyaWdodCleey0yfQ0KICBcY2RvdCBcZnJhY3tcYmV0YX17XGFscGhhfSAoeC9cYWxwaGEpXntcYmV0YSAtIDF9DQpcXQ0KDQpcDQoNClJlYXJyYW5nZToNClxbDQpmKHgpDQo9IFxmcmFjeyhcYmV0YS9cYWxwaGEpKHgvXGFscGhhKV57XGJldGEgLSAxfX0NCiAgICAgICB7XGxlZnRbIDEgKyAoeC9cYWxwaGEpXntcYmV0YX0gXHJpZ2h0XV4yfSwNClxxcXVhZCB4ID4gMA0KXF0NCg0KXA0KDQoNCiMjICoqUXVlc3Rpb24gMjogRGlzdHJpYnV0aW9uIG9mIFJlY292ZXJ5IFRpbWUgZnJvbSBBIFN1cmdlcnkqKg0KDQpUaW1lIHRvIHJlY292ZXJ5IChpbiBkYXlzKSBhZnRlciBhIHNwZWNpZmljIGtuZWUgc3VyZ2VyeSBwcm9jZWR1cmUuIFRoaXMgZm9sbG93cyBhIHR5cGljYWwgKipsb2ctbG9naXN0aWMgcGF0dGVybioqIGluIG1lZGljYWwgc3Vydml2YWwvcmVjb3ZlcnkgYW5hbHlzaXM6DQoNCmBgYA0KOC4yMywgMTIuNzQsIDE0LjgzLCAxNi42MSwgMTguMTYsIDE5LjU1LCAyMC44MCwgMjEuOTQsIDIzLjAwLCAyMy45OCwgMjQuODksIDI1Ljc1LCAyNi41NiwgDQoyNy4zNCwgMjguMDgsIDI4Ljc5LCAyOS40OCwgMzAuMTUsIDMwLjgxLCAzMS40NSwgMzIuMDgsIDMyLjcwLCAzMy4zMSwgMzMuOTIsIDM0LjUzLCAzNS4xMywgDQozNS43MywgMzYuMzMsIDM2LjkzLCAzNy41MywgMzguMTQsIDM4Ljc1LCAzOS4zNywgNDAuMDAsIDQwLjY0LCA0MS4yOSwgNDEuOTUsIDQyLjYzLCA0My4zMywgDQo0NC4wNSwgNDQuNzksIDQ1LjU2LCA0Ni4zNiwgNDcuMjAsIDQ4LjA4LCA0OS4wMiwgNTAuMDMsIDUxLjEyLCA1Mi4zMiwgNTMuNjUNCmBgYA0KQmFzZWQgb24gdGhlIGFib3ZlIGRhdGEgdG8gcGVyZm9ybSB0aGUgZm9sbG93aW5nIGFuYWx5c2lzLg0KDQphKSBVc2luZyBtZXRob2Qgb2YgbW9tZW50IGVzdGltYXRpb24gdG8gZXN0aW1hdGUgJFxhbHBoYSQgYW5kICRcYmV0YSQsIGRlbm90ZWQgYnkgJFxoYXR7XGFscGhhfSQgYW5kICRcaGF0e1xiZXRhfSQsIHJlc3BlY3RpdmVseS4NCg0KYGBgIHtyfQ0KIyAtLS0tLS0tLS0tLS0tLS0gU1RPUklORyBTQU1QTEUgREFUQSBBTkQgQ0FMQ1VMQVRJTkcgTTEgQU5EIE0yIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KcmVjb3Zlcnlfc2FtcGxlIDwtIGMoOC4yMywgMTIuNzQsIDE0LjgzLCAxNi42MSwgMTguMTYsIDE5LjU1LCAyMC44MCwgMjEuOTQsIDIzLjAwLCAyMy45OCwgMjQuODksIDI1Ljc1LCAyNi41NiwgDQoyNy4zNCwgMjguMDgsIDI4Ljc5LCAyOS40OCwgMzAuMTUsIDMwLjgxLCAzMS40NSwgMzIuMDgsIDMyLjcwLCAzMy4zMSwgMzMuOTIsIDM0LjUzLCAzNS4xMywgDQozNS43MywgMzYuMzMsIDM2LjkzLCAzNy41MywgMzguMTQsIDM4Ljc1LCAzOS4zNywgNDAuMDAsIDQwLjY0LCA0MS4yOSwgNDEuOTUsIDQyLjYzLCA0My4zMywgDQo0NC4wNSwgNDQuNzksIDQ1LjU2LCA0Ni4zNiwgNDcuMjAsIDQ4LjA4LCA0OS4wMiwgNTAuMDMsIDUxLjEyLCA1Mi4zMiwgNTMuNjUpDQojIHJlY292ZXJ5X3NhbXBsZTogc3RvcmUgc2FtcGxlIHJlY292ZXJ5IHRpbWVzIGFzIGEgdmVjdG9yDQoNCm0xIDwtIG1lYW4ocmVjb3Zlcnlfc2FtcGxlKQ0KIyBtMTogZmlyc3QgbW9tZW50IG9mIHRoZSBzYW1wbGUNCm0yIDwtIG1lYW4ocmVjb3Zlcnlfc2FtcGxlXjIpDQojIG0yOiBzZWNvbmQgbW9tZW50IG9mIHRoZSBzYW1wbGUNCmBgYA0KDQpgYGAge3J9DQojIC0tLS0tLS0tLS0tLS0tLSBDUkVBVElORyBCRVRBIEVTVElNQVRPUiBGVU5DVElPTiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmJldGFfZXN0aW1hdG9yIDwtIGZ1bmN0aW9uKEssIG0xLCBtMikgDQojIGJldGFfZXN0aW1hdG9yOiBmdW5jdGlvbiB3aXRoIHRocmVlIGFyZ3VtZW50cw0KIyBCOiBCZXRhLiBXZSB3aWxsIHNvbHZlIGZvciB0aGlzIGxhdGVyIHVzaW5nIG51bWVyaWNhbCBhcHByb3hpbWF0aW9uLg0KIyBtMTogZmlyc3QgbW9tZW50IG9mIHRoZSBzYW1wbGUNCiMgbTI6IHNlY29uZCBtb21lbnQgb2YgdGhlIHNhbXBsZQ0Kew0KIyB0aGlzIGJyYWNrZXQgYmVnaW5zIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBmdW5jdGlvbg0KbnVtIDwtIGJldGEoMSArIDIvSywgMSAtIDIvSykNCiMgbnVtOiBpcyB0aGUgbnVtZXJhdG9yIG9mIG91ciBlcXVhdGlvbiBpc29sYXRpbmcgQmV0YQ0KZGVub20gPC0gKGJldGEoMSArIDEvSywgMSAtIDEvSykpXjINCiMgZGVub206IGlzIHRoZSBkZW5vbWluYXRvciBvZiBvdXIgZXF1YXRpb24gaXNvbGF0aW5nIEJldGENCnJlc3VsdCA8LSBudW0gLyBkZW5vbSAtIG0yIC8gbTFeMg0KIyByZXN1bHQ6IHRoZSBzaW1wbGlmaWVkIHN5c3RlbSBvZiBlcXVhdGlvbnMgb2YgcG9wdWxhdGlvbiBhbmQgc2FtcGxlIG1vbWVudHMgd2hlcmUgQmV0YSBpcyBpc29sYXRlZA0KIyBXZSB3aWxsIHNldCB0aGlzIGVxdWFsIHRvIHplcm8gYW5kIHNvbHZlIGZvciBCZXRhIGxhdGVyLiANCnJldHVybihyZXN1bHQpDQp9DQojIHRoaXMgYnJhY2tldCBlbmRzIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBmdW5jdGlvbg0KYGBgDQoNCmBgYCB7cn0NCiMgLS0tLS0tLS0tLS0tLS0tIEdSQVBISU5HIFRPIEVTVElNQVRFIExPQ0FUSU9OIE9GIFggSU5UICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KeF92YWxzIDwtIHNlcSg1LCAxMCwgbGVuZ3RoLm91dCA9IDUwKQ0KIyB4X3ZhbHM6IG51bWVyaWMgdmVjdG9yIG9mIDUwIGVxdWFsbHkgc3BhY2VkIHZhbHVlcyBzdGFydGluZyBhdCA1IGFuZCBlbmRpbmcgYXQgMTANCmRmcmFtZSA8LSBkYXRhLmZyYW1lKHggPSB4X3ZhbHMsIHkgPSBiZXRhX2VzdGltYXRvcih4X3ZhbHMsIG0xLCBtMikpDQojZGZyYW1lOiBkYXRhIGZyYW1lIHdpdGggdHdvIGNvbHVtbnMNCiMgeDogdGhlIHZlY3RvciBvZiBpbnB1dCB2YWx1ZXMgKHhfdmFscykNCiMgeTogdGhlIHZlY3RvciBvZiBlc3RpbWF0ZWQgQmV0YSB2YWx1ZXMNCg0KYmV0YV9lc3RpbWF0b3IucGxvdCA8LSBnZ3Bsb3QoZGZyYW1lLCBhZXMoeCA9IHgsIHkgPSB5KSkgKw0KIyBwbG90IGRmcmFtZSBkYXRhLiB1c2UgeCBhcyB4LWF4aXMgYW5kIHkgYXMgeS1heGlzDQpnZW9tX2xpbmUoY29sb3IgPSAic3RlZWxibHVlIiwgc2l6ZSA9IDEpICsNCiMgZHJhdyBhIGJsdWUgbGluZSBjb25uZWN0aW5nIGFsbCB0aGUgZGF0YSBwb2ludHMNCmdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArDQojIGNyZWF0ZSBkYXNoZWQgbGluZSBhbG9uZyB0aGUgeC1heGlzDQpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKw0KIyBjcmVhdGUgZGFzaGVkIGxpbmUgYWxvbmcgdGhlIHktYXhpcw0KbGFicyh0aXRsZSA9ICJUaGUgY3VydmUgb2YgZnVuY3Rpb24gYmV0YV9lc3RpbWF0b3IiLA0KeCA9ICJCZXRhX0VzdGltYXRvciIsIA0KeSA9ICJIZWlnaHQgb2YgRnVuY3Rpb24iKSArDQojIENyZWF0ZSB0aXRsZXMNCnRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KIyBDZW50ZXJzIHRoZSBwbG90IHRpdGxlDQpwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMzUsIHIgPSAyMCwgYiA9IDMwLCBsID0gMzAsIHVuaXQgPSAicHQiKSkNCiMgQWRkcyBleHRyYSBwYWRkaW5nIGFyb3VuZCB0aGUgZ3JhcGggc28gdGl0bGVzIGFyZSBsZXNzIGNyYW1wZWQNCmdncGxvdGx5KGJldGFfZXN0aW1hdG9yLnBsb3QpICMgUmVhZHMgdGhlIHBsb3Qgd2UgY3JlYXRlZCBhbmQgY3JlYXRlcyBhbiBpbnRlcmFjdGl2ZSB3aWRnZXQNCmBgYA0KDQoqKkluc2lnaHQqKjoNClRoZSBYLWludGVyY2VwdCBpcyBzb21ld2hlcmUgYmV0d2VlbiA1IGFuZCA3LiBJbiB0aGUgbmV4dCBzdGVwLCB3ZSB3aWxsIGxvb2sgZm9yIGEgc29sdXRpb24gKGJldGEgaGF0KSBhbG9uZyB0aGF0IGludGVydmFsLg0KDQoNCmBgYCB7cn0NCiMgLS0tLS0tLS0tLS0tLS0tIFVTSU5HIE5VTUVSSUNBTCBBUFBST1hJTUFUSU9OIFRPIEZJTkQgQkVUQSBIQVQgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KYmV0YV9oYXQgPC0gdW5pcm9vdChiZXRhX2VzdGltYXRvciwgaW50ZXJ2YWwgPSBjKDUsIDcpLCBtMSwgbTIpJHJvb3QNCmFscGhhX2hhdCA8LSBtMSAvIGJldGEoMSArIDEvYmV0YV9oYXQsIDEgLSAxL2JldGFfaGF0KQ0KIyBXZSBwbHVnIGJldGEgaGF0IGJhY2sgaW50byB0aGUgZXF1YXRpb24gZm9yIHRoZSBmaXJzdCBtb21lbnQgdG8gZmluZCBhbHBoYSBoYXQNCg0KcGFuZGVyKGNiaW5kKGJldGFfaGF0ID0gYmV0YV9oYXQsIGFscGhhX2hhdCA9IGFscGhhX2hhdCkpIyBjYmluZDogY3JlYXRlcyBhIHR3byBjb2x1bW4gbWF0cml4IGZvciBiZXRhX2hhdCBhbmQgYWxwaGFfaGF0LiBUaXRsZXMgYXJlIGFscGhhX2hhdCBhbmQgYmV0YV9oYXQuIHBhbmRlciByZW5kZXJzIGEgY2xlYW4gcmVhZGFibGUgdGFibGUNCmBgYA0KDQpiKSBTaW5jZSB0aGUgbW9tZW50IGVzdGltYXRlcyAkXGhhdHtcYWxwaGF9JCBhbmQgJFxoYXR7XGJldGF9JCBhcmUgcmFuZG9tLCBjb25zdHJ1Y3QgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMgZm9yIGVhY2guIFRvIHZpc3VhbGl6ZSB0aGVzZSBkaXN0cmlidXRpb25zLCBwbG90IHNlcGFyYXRlIGJvb3RzdHJhcCBoaXN0b2dyYW1zIGZvciAkXGhhdHtcYWxwaGF9JCBhbmQgJFxoYXR7XGJldGF9JC4gIHRoZW4sIG92ZXJsYXkgYSBzbW9vdGggZGVuc2l0eSBjdXJ2ZSBvbiBlYWNoIGhpc3RvZ3JhbSB1c2luZyBHYXVzc2lhbiBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uLiBGaW5hbGx5LCBkZXNjcmliZSB0aGUgcGF0dGVybnMgb2YgdGhlc2UgZGVuc2l0eSBjdXJ2ZXMuDQoNCmBgYHtyfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLURFRklOSU5HIFRIRSBCT09UU1RSQVAgRlVOQ1RJT04gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmJvb3RzdHJhcF9tb21lbnRzIDwtIGZ1bmN0aW9uKGRhdGEsIEIpIA0KIyBib290c3RyYXBfbW9tZW50czogZnVuY3Rpb24gd2l0aCB0d28gYXJndW1lbnRzDQojIGRhdGE6IHRoZSByYW5kb20gc2FtcGxlIGZyb20gdGhlIHBvcHVsYXRpb24gd2l0aCB3aGljaCB5b3Ugd2lsbCBtYWtlIGJvb3RzdHJhcCBzYW1wbGVzDQojIEI6IHRoZSBudW1iZXIgb2YgYm9vdHN0cmFwIHNhbXBsZXMgeW91IHBsYW4gdG8gY3JlYXRlDQp7DQojIHRoaXMgYnJhY2tldCBiZWdpbnMgdGhlIGRlZmluaXRpb24gb2YgdGhlIGZ1bmN0aW9uDQpuIDwtIGxlbmd0aChkYXRhKQ0KIyBuOiB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBpbiB5b3VyIHJhbmRvbSBzYW1wbGUNCnRfb2JzX2ZpcnN0X21vbSA8LSBtZWFuKGRhdGEpDQp0X29ic19zZWNvbmRfbW9tIDwtIG1lYW4oZGF0YV4yKQ0KIyB0X29iczogdGhlIGNvbXB1dGVkIHN0YXRpc3RpYyBmb3IgeW91ciBvcmlnaW5hbCByYW5kb20gc2FtcGxlLiBUaGlzIG9ubHkgbmVlZHMgdG8gYmUgY29tcHV0ZWQgb25jZS4NCiMgdF9vYnNfZmlyc3RfbW9tIHJlcHJlc2VudHMgeW91ciBmaXJzdCBzYW1wbGUgbW9tZW50IGFuZCB0X29ic19zZWNvbmRfbW9tIGlzIHlvdXIgc2Vjb25kIHNhbXBsZSBtb21lbnQuDQojIHRoaXMgd2lsbCBub3QgYmVjb21lIHBhcnQgb2YgeW91ciBib290c3RyYXAgZGlzdHJpYnV0aW9uLiBUaGlzIGlzIHlvdXIgYWN0dWFsIGVzdGltYXRlIGZyb20gdGhlIHJlYWwgd29ybGQuDQpib290X2ZpcnN0X21vbV9kaXN0IDwtIG51bWVyaWMoQikNCmJvb3Rfc2Vjb25kX21vbV9kaXN0IDwtIG51bWVyaWMoQikNCiMgYm9vdF9kaXN0OiBlbXB0eSB2ZWN0b3Igb2YgbGVuZ3RoIEIgdGhhdCB3aWxsIGV2ZW50dWFsbHkgc3RvcmUgYWxsIHRoZSBib290c3RyYXAgc3RhdGlzdGljcyB5b3Ugd2lsbCBjb21wdXRlDQoNCmZvciAoYiBpbiAxOkIpIA0Kew0KIyBldmVyeXRoaW5nIGluc2lkZSBvZiB0aGlzIGJyYWNrZXQgd2lsbCBsb29wIEIgdGltZXMsIGZpbGxpbmcgdGhlIHZlY3RvcnMgYm9vdF9maXJzdF9tb21fZGlzdCBhbmQgYm9vdF9zZWNvbmRfbW9tX2Rpc3QNCmluZGljZXMgPC0gc2FtcGxlKDE6biwgbiwgcmVwbGFjZSA9IFRSVUUpDQojIHRoZSBzYW1wbGUgZnVuY3Rpb24gc2FtcGxlcyB3aXRoIHJlcGxhY2VtZW50IGZyb20gdGhlIHZlY3RvciAxOm4gKHRoZSBpbnRlZ2VycyAxLDIsMywgLi4uIG4pIHVudGlsIHNhbXBsZSBzaXplIGlzIG4NCiMgdGhlIHJlc3VsdCBpcyBhIHZlY3RvciBjYWxsZWQgaW5kaWNlcyB3aGljaCBzdG9yZXMgdGhlIHBvc2l0aW9uIG9mIGRhdGEgdmFsdWVzIHdlJ2QgbGlrZSBpbiBvdXIgYm9vdHN0cmFwIHNhbXBsZQ0KYm9vdHN0cmFwX3NhbXBsZSA8LSBkYXRhW2luZGljZXNdDQojIHdlIGluZGV4IG91ciBkYXRhIHdpdGggdGhlIGluZGljZXMgdmVjdG9yIHRvIGNyZWF0ZSBvdXIgYm9vdHN0cmFwIHNhbXBsZQ0KYm9vdF9maXJzdF9tb21fZGlzdFtiXSA8LSBtZWFuKGJvb3RzdHJhcF9zYW1wbGUpDQojIHdlIGNvbXB1dGUgdGhlIGZpcnN0IG1vbWVudCBvZiBvdXIgYm9vdHN0cmFwIHNhbXBsZSANCmJvb3Rfc2Vjb25kX21vbV9kaXN0W2JdIDwtIG1lYW4oYm9vdHN0cmFwX3NhbXBsZV4yKQ0KIyB3ZSBjb21wdXRlIHRoZSBzZWNvbmQgbW9tZW50IG9mIG91ciBib290c3RyYXAgc2FtcGxlIA0KIyBhbmQgdGhlbiBmZWVkIHRob3NlIHZhbHVlcyBpbnRvIG91ciBib290c3RyYXAgZGlzdHJpYnV0aW9uIHZlY3RvcnMsIGZpbGxpbmcgaW4gcG9zaXRpb24gYg0KfQ0KIyBldmVyeXRoaW5nIGFmdGVyIHRoaXMgYnJhY2tldCBpcyBvdXRzaWRlIHRoZSBsb29wDQogIA0KcmV0dXJuKGxpc3Qob2JzZXJ2ZWRfZmlyc3RfbW9tID0gdF9vYnNfZmlyc3RfbW9tLCBvYnNlcnZlZF9zZWNvbmRfbW9tID0gdF9vYnNfc2Vjb25kX21vbSwgZGlzdHJpYnV0aW9uX2ZpcnN0X21vbSA9IGJvb3RfZmlyc3RfbW9tX2Rpc3QsDQpkaXN0cmlidXRpb25fc2Vjb25kX21vbSA9IGJvb3Rfc2Vjb25kX21vbV9kaXN0KSkNCiMgc2F2ZSBhbGwgb2Ygb3VyIGRhdGEgaW4gYSBsaXN0DQp9DQojIHRoaXMgYnJhY2tldCBlbmRzIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBmdW5jdGlvbg0KYGBgDQoNCmBgYHtyfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLSBDUkVBVElORyBPVVIgQk9PVFNUUkFQIEVTVElNQVRFUyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KYm9vdF9tb21zIDwtIGJvb3RzdHJhcF9tb21lbnRzKHJlY292ZXJ5X3NhbXBsZSw1MDAwKQ0KIyBib290X21vbXM6IGEgbGlzdCBvZiA1MDAwIGJvb3RzdHJhcCBmaXJzdCBtb21lbnRzLCA1MDAwIGJvb3RzdHJhcCBzZWNvbmQgbW9tZW50cywgYXMgd2VsbCBhcyB0aGUgZmlyc3QgYW5kIHNlY29uZCBtb21lbnRzIGZyb20gdGhlIHNhbXBsZSBkYXRhLg0KDQpiZXRhX2Jvb3RzdHJhcF9lc3RpbWF0ZXMgPC0gbnVtZXJpYyhsZW5ndGgoYm9vdF9tb21zJGRpc3RyaWJ1dGlvbl9maXJzdF9tb20pKQ0KYWxwaGFfYm9vdHN0cmFwX2VzdGltYXRlcyA8LSBudW1lcmljKGxlbmd0aChib290X21vbXMkZGlzdHJpYnV0aW9uX2ZpcnN0X21vbSkpDQojIENyZWF0aW5nIGVtcHR5IHZlY3RvcnMgdGhlIGxlbmd0aCBvZiBkaXN0cmlidXRpb25fZmlyc3RfbW9tDQojIFdlIHdpbGwgdXNlIHRoZXNlIHRvIHN0b3JlIG91ciBhbHBoYSBhbmQgYmV0YSBlc3RpbWF0ZXMNCg0KZm9yIChpIGluIDE6bGVuZ3RoKGJldGFfYm9vdHN0cmFwX2VzdGltYXRlcykpIA0KIyBldmVyeXRoaW5nIGluc2lkZSBvZiB0aGlzIGJyYWNrZXQgd2lsbCBsb29wIDUwMDAgdGltZXMsIGZpbGxpbmcgdGhlIHZlY3RvcnMgYmV0YV9ib290c3RyYXBfZXN0aW1hdGVzIGFuZCBhbHBoYV9ib290c3RyYXBfZXN0aW1hdGVzDQp7DQptMWIgPC0gYm9vdF9tb21zJGRpc3RyaWJ1dGlvbl9maXJzdF9tb21baV0NCiMgd2UgZ2F0aGVyIHRoZSBpLXRoIGZpcnN0IGJvb3RzdHJhcCBtb21lbnQgDQptMmIgPC0gYm9vdF9tb21zJGRpc3RyaWJ1dGlvbl9zZWNvbmRfbW9tW2ldDQojIHdlIGdhdGhlciB0aGUgaS10aCBzZWNvbmQgYm9vdHN0cmFwIG1vbWVudCANCmJldGFfYm9vdHN0cmFwX2VzdGltYXRlc1tpXSA8LSB1bmlyb290KGJldGFfZXN0aW1hdG9yLCBpbnRlcnZhbCA9IGMoMiwgMTUpLCBtMSA9IG0xYiwgbTIgPSBtMmIpJHJvb3QNCiMgd2UgY29tcHV0ZSB0aGUgdGhlIGktdGggYmV0YSBlc3RpbWF0ZSANCmFscGhhX2Jvb3RzdHJhcF9lc3RpbWF0ZXNbaV0gPC0gbTFiIC8gYmV0YSgxICsgMS9iZXRhX2Jvb3RzdHJhcF9lc3RpbWF0ZXNbaV0sIDEgLSAxL2JldGFfYm9vdHN0cmFwX2VzdGltYXRlc1tpXSkNCiMgd2UgY29tcHV0ZSB0aGUgdGhlIGktdGggYWxwaGEgZXN0aW1hdGUgDQojIGFuZCB0aGVuIGZlZWQgdGhvc2UgdmFsdWVzIGludG8gb3VyIGJvb3RzdHJhcCBlc3RpbWF0ZSB2ZWN0b3JzLCBmaWxsaW5nIGluIHBvc2l0aW9uIGkNCn0NCmBgYA0KDQoqKkFuc3dlcioqOg0KVGhlIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgYWxwaGEgaGF0IGlzIGFwcHJveGltYXRlbHkgbm9ybWFsLiBJdCBhcHBlYXJzIGJlbGzigJFzaGFwZWQsIHVuaW1vZGFsLCBhbmQgc3ltbWV0cmljIGFyb3VuZCBpdHMgY2VudGVyLiBJbiBjb250cmFzdCwgdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gb2YgYmV0YSBoYXQgaXMgbm90aWNlYWJseSByaWdodOKAkXNrZXdlZC4gVGhpcyBkaWZmZXJlbmNlIGFyaXNlcyBmcm9tIHRoZSB3YXkgZWFjaCBlc3RpbWF0b3IgaXMgY29uc3RydWN0ZWQuIFRoZSBlc3RpbWF0b3IgYWxwaGEgaGF0IGlzIGEgc21vb3RoLCBuZWFybHkgbGluZWFyIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBzYW1wbGUgbWVhbi4gTWVhbndoaWxlLCBiZXRhIGhhdCBpcyBvYnRhaW5lZCBhcyB0aGUgbnVtZXJpY2FsIHJvb3Qgb2YgYSBub25saW5lYXIgbW9tZW50IGVxdWF0aW9uIGludm9sdmluZyB0aGUgcmF0aW8g8J2RmjIgLyDwnZGaMV4gMiAuIEJlY2F1c2UgdGhlIHNlY29uZCBtb21lbnQg8J2RmjIgaGFzIGhpZ2hlciBzYW1wbGluZyB2YXJpYWJpbGl0eSBhbmQgaXMgbW9yZSBzZW5zaXRpdmUgdG8gbGFyZ2Ugb2JzZXJ2YXRpb25zLCB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mIGJldGEgaGF0IGRldmVsb3BzIGEgbG9uZ2VyIHJpZ2h0IHRhaWwuDQoNCmBgYCB7cn0NCiMgLS0tLS0tLS0tLS0tLS0tLS0gR1JBUEhJTkcgT1VSIEJPT1RTVFJBUCBFU1RJTUFURSBESVNUUklCVVRJT05TIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpkZl9hbHBoYSA8LSBkYXRhLmZyYW1lKGFscGhhX2hhdCA9IGFscGhhX2Jvb3RzdHJhcF9lc3RpbWF0ZXMpDQojIGRmX2FscGhhOiBnZ3Bsb3QgY2Fubm90IHRha2UgdmVjdG9ycywgc28gd2UgbmVlZCB0byBjcmVhdGUgYSBkYXRhIGZyYW1lIHRvIGdpdmUgaXQNCmRmX2JldGEgIDwtIGRhdGEuZnJhbWUoYmV0YV9oYXQgID0gYmV0YV9ib290c3RyYXBfZXN0aW1hdGVzKQ0KDQpwX2FscGhhIDwtIGdncGxvdChkZl9hbHBoYSwgYWVzKHggPSBhbHBoYV9oYXQpKSArDQpnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSwgYmlucyA9IDMwLCBmaWxsID0gInNreWJsdWUiLCBjb2xvciA9ICJ3aGl0ZSIsIGFscGhhID0gMC43KSArDQpnZW9tX2RlbnNpdHkoa2VybmVsID0gImdhdXNzaWFuIiwgY29sb3IgPSAiYmx1ZSIsIGxpbmV3aWR0aCA9IDEuMikgKw0KbGFicygNCnRpdGxlID0gIkJvb3RzdHJhcCBEaXN0cmlidXRpb24gb2YgzrHMgiIsDQp4ID0gZXhwcmVzc2lvbihoYXQoYWxwaGEpKSwNCnkgPSAiRGVuc2l0eSINCikgKw0KdGhlbWVfbWluaW1hbCgpDQpwX2FscGhhDQoNCnBfYmV0YSA8LSBnZ3Bsb3QoZGZfYmV0YSwgYWVzKHggPSBiZXRhX2hhdCkpICsNCmdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBiaW5zID0gMzAsIGZpbGwgPSAic2FsbW9uIiwgY29sb3IgPSAid2hpdGUiLCBhbHBoYSA9IDAuNykgKw0KZ2VvbV9kZW5zaXR5KGtlcm5lbCA9ICJnYXVzc2lhbiIsIGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEuMikgKw0KbGFicygNCnRpdGxlID0gIkJvb3RzdHJhcCBEaXN0cmlidXRpb24gb2YgzrLMgiIsDQp4ID0gZXhwcmVzc2lvbihoYXQoYmV0YSkpLA0KeSA9ICJEZW5zaXR5Ig0KKSArDQp0aGVtZV9taW5pbWFsKCkNCnBfYmV0YQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg==